import ModuleColection from './module/module-colection';
import { forEachValue } from './utils';
let Vue;

// root = {
//     _raw: 默认显示用户原始内容,
//     _children:{
//         a:{_raw: a模块的原始内容, _children:{},state:aState},
//         b:{_raw: n模块的原始内容, _children:{},state:bState},
//     },
//     state:'更模块的状态'
// }

// store  store属性
// path 构造的递归栈结构
// module 当前安装的模块
const installModule = (store, path, module, rootState) => { // 注册所有的getter，mutation，getter
    // rootState: {a:b}
    // 计算当前的一个命名空间，在订阅的时候 每个key前面都增加一个命名空间
    // root -> 根开始查找 path路径 [a,c] a/c
    let namespaced = store._module.getNamespace(path);
    console.log(namespaced);
    if (path.length > 0) { // 循环是子模块 [a,c]
        // 给rootState 添加模块的属性
        let parent = path.slice(0, -1).reduce((memo, current) => memo[current], rootState);
        // 后续数据可能是动态注册的模块，如果原来没有属性，新增不会导致视图更新
        Vue.set(parent, path[path.length - 1], module.state);
    }


    module.forEachMutation((mutation, key) => {
        store._mutations[namespaced + key] = (store._mutations[namespaced + key] || [])
        store._mutations[namespaced+key].push((payload) => {
            mutation(module.state, payload); // mutation执行
        });
    });

    module.forEachAction((actions, key) => {
        store._actions[namespaced + key] = (store._actions[key] || [])
        store._actions[namespaced+key].push((payload) => {
            actions(store, payload); // action执行
        });
    });

    module.forEachGetter((getter, key) => {
        store._wrappedGetters[key] = function () {
            return getter(module.state); // 计算属性执行
        }
    });
    module.forEachChildren((child, key) => {
        installModule(store, path.concat(key), child, rootState);
    })
}

function setStoreVM(store, state) {


    let computed = {};
    store.getters = {}; // 用户最后会访问这个复习
    forEachValue(store._wrappedGetters, (fn, key) => {
        computed[key] = () => {
            return fn(store.state)
        }
        Object.defineProperty(store.getters, key, {
            get: () => store._vm[key]
        })
    })
    store._vm = new Vue({
        data: {
            $$state: state
        },
        computed
    })
}

class Store {
    constructor(options) {
        // 1. 用户的数据进行格式化操作
        const store = this;
        store._module = new ModuleColection(options);

        store._actions = {} // 收集所有模块的action
        store._actions = {} // 收集所有模块的actions
        store._mutations = {} // 收集所有模块的mutations
        store._wrappedGetters = {} // 收集所有模块的getter

        let state = options.state;
        installModule(store, [], store._module.root, state);
        setStoreVM(store, state);
        console.log('====================================')
        console.log(store._vm._data.$$state)
        console.log('====================================')
    }

    commit = (type, payload) => { // this永远指向store容器
        this._mutations[type].forEach(fn => fn(payload))
    }

    dispatch = (type, payload) => { // this永远指向store容器
        this._actions[type].forEach(fn => fn(payload))
    }

    get state() {
        return this._vm._data.$$state;
    }

}

const Vuex = {
    Store,
    install(_Vue) {
        Vue = _Vue;
        // 需要获取到父组件的store属性，每个组件运行的时候都能拿到store
        Vue.mixin({
            // 混入创建之初
            beforeCreate() {
                const options = this.$options;
                if (options.store) { // 根组件
                    this.$store = options.store; // 根组件上有一个$store 属性
                } else { // 子组件、平级组件(排除平级组件)
                    // 判断非根组件，获取组件的$store
                    if (this.$parent && this.$parent.$store) {
                        this.$store = this.$parent.$store;
                    }
                }
            }
        })
    }
}

export default Vuex;